Authoring a compelling virtual world that looks good on VRML viewers from PCs up to Reality Engines is not easy. Most of the effort will be grunt work - making multiple versions of your models that range in polygonal complexity, yet still look good. By doing this, it is possible to make VRML worlds which look their best on all viewers, without writing to the lowest common denominator, and without excluding low-end machines from viewing your scenes.
This document describes suggestions for getting the best performance out of all viewers, but with a decided bias towards WebSpace (tm), the VRML viewer. If you have a good grasp of the WWWAnchor, WWWInline and LOD nodes, you can just cut to the chase.
This document assumes you are familiar with the Open Inventor file format, and with the VRML specification. This and other related info can be obtained from:
Use your favorite modeler to create model geometry and scene placement. Here are some tips to keep in mind:
An Inventor to VRML translator, ivToVRML, will be available soon.
It converts standard Inventor files into the subset of Inventor which is VRML.This subset is described in the Inventor/VRML Overview.
This group node is used to allow applications to switch between various representations of objects automatically. The children of this node typically represent the same object or objects at varying levels of detail, from highest detail to lowest.
The specified center point of the LOD is transformed by the current transformation into world space, and the distance from the transformed center to the world-space eye point is calculated. If the distance is less than the first value in the ranges array, then the first child of the LOD group is drawn. If between the first and second values in the ranges array, the second child is drawn, etc. If there are N values in the ranges array the LOD nodes should have N+1 children. Specifying too few children will result in the last child being used repeatedly for the lowest levels of detail; extra children will be ignored if too many children are specified. Each value in the ranges array should be less than the previous value, otherwise results are undefined.
FILE FORMAT/DEFAULTS LOD { ranges [ ] # MFFloat center 0 0 0 # SFVec3f }
A good rule of thumb is to make at least three versions of each model:
These polygon counts are only representative. As discussed in a later section, you need to also manage the overall scene complexity.
You may also want to have a fourth child which has no geometry, if it is OK for the object to disappear when it is very far away. Which leads us to the next topic...
Note: For clarity, this example does not use the WWWInline node. However, as described in the next section, judicious use of the WWWInline node in combination with the LOD node is necessary to achieve optimal viewer performance, especially when pulling data across the net.
# A mountain object DEF Everest LOD { ranges [100, 1000, 10000] # n ranges for n+1 children center 0 1000 0 # assuming mountain is 2000 high # High complexity, textured DEF EverestHi Separator { Separator { # Coordinates, textures and geometry for a 1200 # polygon version of the mountain. ... } } # Medium complexity DEF EverestMed Separator { Separator { # Coordinates and geometry for a 600 # polygon version of the mountain. } } # Low complexity DEF EverestLow Separator { Separator { # Coordinates, textures and geometry for a 8 # polygon version of the mountain. Perhaps just # two four-sided pyramids } } # Invisible version of the mountain. Rendered when # the mountain is really far away. Group { } }
The WWWInline is used to delay the loading of some portion of a VRML scene. The URL specified by the Inline node is only fetched by the viewer when it is needed, such as when the viewer decides that it wants to render what is represented by the WWW Inline.
For this reason, it is natural to represent the children of an LOD node as WWWInline nodes. Imagine the example from above was accessed by a viewer on a low-end PC. It would go to all the trouble of reading all four children of the LOD node, including the 1200 polygon textured version, even though it probably will never render it.
If instead we wrap the LOD children in WWWInline nodes, a given child will only be read if the LOD node decides it should be rendered. This saves unneccesary reading of data over a potentially slow network connection.
Since we want to insure that something is read right away to be available for display, do not wrap the lowest complexity version of the model in an Inline node. Also, note that some viewers (like the SGI viewer) will read the WWWInline nodes as a background process, 'popping' the result into the viewer when it becomes available. By not inlining the low-res version, the user still sees something while the higher res version is being fetched.
It is critical to specify an accurate bounding box in the WWWInline node. The bounding box allows the LOD node to cull a WWWInline node without actually reading its contents. Use the vrmlinfo
utility that was shipped with the WebSpace alpha distribution to find bounding box information about a VRML or Inventor object. Also note that the ivToVRML utility will fill in the bounding box info automatically.
Since we will wrap our objects in WWWInline nodes, we need to keep them as separate VRML files...
#VRML V1.0 ascii #File EverestHi.vrml Separator { # Coordinates, textures and geometry for a 1200 # polygon version of the mountain. ... } #VRML V1.0 ascii #File EverestMed.vrml Separator { # Coordinates and geometry for a 600 # polygon version of the mountain. }
Then we have our world, which references these files. Note that the URL can be relative to the current URL.
# A mountain object DEF Everest LOD { ranges [100, 1000, 10000] # n ranges for n+1 children center 0 1000 0 # assuming mountain is 2000 high # Hi Complexity DEF EverestHi Separator { WWWInline { name "EverestHi.vrml" bboxSize 200 400 200 bboxCenter 0 200 0 } } # Medium complexity DEF EverestMed Separator { WWWInline { name "EverestMed.vrml" bboxSize 200 400 200 bboxCenter 0 200 0 } } # Low complexity, not inlined DEF EverestLow Separator { Separator { # Coordinates, textures and geometry for a 8 # polygon version of the mountain. Perhaps just # two four-sided pyramids } } # Invisible version of the mountain. Rendered when # the mountain is really far away. Group { } }
Besides managing the complexity of individual objects in the scene, it is important to keep the overall scene complexity in mind. For any given position of the camera, you must ask "What will be in view?" and "How many polygons am I trying to draw?" It is important that for a given view, you do not try to draw too much for a given viewer platform.
Here are some polygon-per-scene guidelines for a small range of platforms, assuming 15 frames per second:
Pentium-90, NT 1300 (size?, lit, no texture) XL (Indy/Indigo2) 1600 (10x10, lit, no texture) XZ (Indy/Indigo2) 4400 (10x10, lit, no texture) Extreme (Indigo2) 10300 (10x10, lit, no texture) RealityEngine2 30000 (10x10 [50 pixel/tri] tmesh, lit, textured)
Finally, edit your VRML scene and add WWWAnchor nodes around those objects that should be hyperlinked. Note that Anchors can be used to limit the size of a scene to a manageable complexity. For example, instead of having a wide open space with all objects visible, have closed rooms, where clicking on a door takes you to a new scene:
# Room Separator { Separator { # closed room geometry here } # Door to next room WWWAnchor { name "rooms/NextRoom.vrml" # Door Geometry Separator { Transform { translation 3 4 1 rotation 0 1 0 1.5407 } LOD { ranges [4, 16] center 1.5 4 .05 WWWInline { name "geom/DoorHi.vrml" bboxSize 3 8 .1 bbox Center 0 0 0 } WWWInline { name "geom/DoorMed.vrml" bboxSize 3 8 .1 bbox Center 0 0 0 } Separator { Cube { width 3 height 8 depth .1 } } } } } }
WebSpace will look for these hints in a VRML file.
This specifies the preferred viewing paradigm for the scene. Possible choices are "examiner" and "walk".
DEF Viewer Info { string "examiner" }
This specifies the default walking speed for the walk viewer. The velocity is in "units per second." For example, if your world is defined in terms of meters (which by the way, is what the VRML spec defines), the following hint will move the user 28 meters forward if the user holds the forward key for one second:
DEF ViewerSpeed Info { string "28.0" }
If this hint is not specified, WebSpace will try to pick a reasonable speed based on the size of the scene.
This title hint will be displayed in the WebSpace title bar.
DEF Title Info { string "My VRML Scene Title" }
This hint defines scene information that will be displayed, along with the title and URL, if the user chooses "Document Info" from the WebSpace File menu.
DEF SceneInfo Info { string "This scene was designed by Bozo T. Clown in 1995 using the ClownEdit modeler." }
This will set the background color of the WebSpace window to the given RGB value:
DEF BackgroundColor Info { string ".2 .2 .2" }
Vantage points are interesting places to put the camera in the scene, like "Kodak Moment" stops. To have vantage points in your scene, simply name your cameras using DEF, and put them under a switch node:
DEF Cameras Switch { whichChild 0 DEF Home_View PerspectiveCamera { position 123 0 234 orientation 0 1 0 .1 } DEF Treasure_View PerspectiveCamera { position 456 0 234 orientation 0 1 0 .8 } }
The names of these cameras will be added to the vantage points UI in WebSpace. The Switch node should be named "Cameras" as shown. The value of whichChild
field will determine the default camera. If whichChild
is not set, the first camera will be used.
By default, WebSpace will automatically adjust the near and far clipping planes to be as tight as possible around the scene, based on the scene's bounding box. Occasionally, this will produce undesired results, such as having a near clipping plane which is too far away from the eye.
If you are experiencing this problem, use this hint:
DEF AutoClip Info { string "off" }
If you do use this hint, make sure that all of the cameras defined in your scene have appropriate values set for nearDistance and farDistance.
File compression of VRML files is supported, and can dramatically reduce the size of VRML files, which subsequently reduces required network bandwidth. After authoring your VRML files, you can compress them with 'compress' or 'gzip' (preferred). The gzip executable (and even source source code) is included with the Netscape distribution.
Files which you compress with 'compress' should end in .wrl.Z
Files which you compress with 'gzip' should end in .wrl.gz (preferred) or .wrl.z or .wrz
Group
node as the last child if it is OK for the object to disappear entirely when it is very far away. No name hint is necessary for the invisible child, if it exists.
vrmlinfo
utility, shipped with the WebSpace alpha distribution, to count the polygons in an object, and do determine the bounding box info needed by the WWWInline node.